package com.example.myapplication.jetpack.livedata;

import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ymz0427 on 2022/12/7
 */
public class LiveDataBus {

    public static final String TAG = "LiveDataBus";

    private final Map<String, MutableLiveData<Object>> map = new HashMap<>();

    private boolean hook = false;

    private static class Holder {
        private static final LiveDataBus instance = new LiveDataBus();
    }

    public static LiveDataBus getInstance() {
        return Holder.instance;
    }

    public LiveDataBus hook(boolean hook) {
        this.hook = hook;
        return this;
    }

    @SuppressWarnings("unchecked")
    public synchronized <T> MutableLiveData<T> with(String key, Class<T> clazz) {
        MutableLiveData<Object> liveData = map.get(key);
        if (liveData == null) {
            liveData = new InnerLiveData<>(hook);
            map.put(key, liveData);
        }
        return (MutableLiveData<T>) liveData;
    }

    private static class InnerLiveData<T> extends MutableLiveData<T> {

        private final boolean hook;

        InnerLiveData(boolean hook) {
            this.hook = hook;
        }

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            // 如果是onResume之前，
            super.observe(owner, observer);
            if (hook) {
                // 这个hook处理就数据粘性只针对onResume之前的addObserver生效，（activity的performStart方法中先执行activity的onStart方法，
                // 再分发生命周期事件到fragment，从而activity的getLifecycle()此时才会改变状态为STARTED
                hook(observer);
            }
            Log.d(TAG, "liveData.observer(owner," + observer.hashCode() + ")");
        }

        /**
         * 改变observer的mLastVersion， 而不是改变mVersion，防止其他observer接收不到数据
         */
        private void hook(Observer<? super T> observer) {
            try {
                //1.得到mLastVersion
                //获取到LivData的类中的mObservers对象
                Class<LiveData> liveDataClass = LiveData.class;
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                //获取到这个成员变量的对象
                Object mObserversObject = mObserversField.get(this);
                //得到map对象的class对象
                Class<?> mObserversClass = mObserversObject.getClass();
                //获取到mObservers对象的get方法
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                //执行get方法
                Object invokeEntry = get.invoke(mObserversObject, observer);
                //取到entry中的value
                Object observerWraper = null;
                if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
                    observerWraper = ((Map.Entry) invokeEntry).getValue();
                }
                if (observerWraper == null) {
                    throw new NullPointerException("observerWraper is null");
                }
                //得到observerWraperr的类对象
                Class<?> supperClass = observerWraper.getClass().getSuperclass();
                Field mLastVersion = supperClass.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
                //2.得到mVersion
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);
                //3.mLastVersion=mVersion
                Object mVersionValue = mVersion.get(this);
                mLastVersion.set(observerWraper, mVersionValue);

            } catch (Exception e) {

            }
        }
    }
}
